﻿using System;
using System.Linq;
using System.ComponentModel;

namespace N2.ComponentModel
{
	using N2;
	using Details;
	
	internal sealed class ContentItemPropertyDescriptor
		: PropertyDescriptor
	{
		#region Fields

		readonly PropertyDescriptor parentDescriptor;
		readonly ContentDetail instance;
		readonly string category;

		#endregion Fields

		#region Constructors

		public ContentItemPropertyDescriptor(
				PropertyDescriptor parent,
				ContentDetail contentDetail,
				string category)
			:base(parent)
		{
			this.parentDescriptor = parent;
			this.instance = contentDetail;
			this.category = category;
		}
		
		#endregion Constructors

		public override string Category {
			get {
				return
					this.category;
			}
		}

		public override string DisplayName {
			get {
				return this.instance.Name;
			}
		}

		public override bool CanResetValue(object component)
		{
			return this.parentDescriptor.CanResetValue(component);
		}

		public override Type ComponentType
		{
			get { return typeof(ContentItem); }
		}

		public override object GetValue(object component) {
			if (!(component is ContentItem)) {
				throw new ArgumentException("component");
			}
			
			var _category = (component as ContentItem).GetDetailCollection(this.category, false);

			if (null != _category) {
				return (
					from _cd in _category.Details
					where _cd.Name == this.instance.Name
					select _cd.Value
				).FirstOrDefault();
			}
			
			return null;
		}

		public override bool IsReadOnly {
			get {
				return
					this.instance is StringDetail
						|| this.instance is IntegerDetail
						|| this.instance is DoubleDetail
					? false
					: this.parentDescriptor.IsReadOnly;
			}
		}

		public override Type PropertyType {
			get { return this.instance.Value.GetType(); }
		}

		public override void ResetValue(object component)
		{
			this.ResetValue(component);
		}

		public override void SetValue(object component, object value)
		{
			(component as ContentItem)[this.instance.Name] = value;
		}

		public override bool ShouldSerializeValue(object component)
		{
			return
				this.parentDescriptor.ShouldSerializeValue(component);
		}
	}
}
